package com.shenzw.common.serial;

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.DesensitizedUtil;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.shenzw.common.aop.anno.Desensitization;
import com.shenzw.common.coonstants.DesensitizationTypeEnum;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;

import java.io.IOException;
import java.util.Objects;

/**
 * 自定义序列化类
 *
 * @author shenzw
 * @date 2024/3/4
 */
@NoArgsConstructor
@AllArgsConstructor
public class DesensitizationSerialize extends JsonSerializer<String> implements ContextualSerializer {

    /**
     * 自定义序列化枚举
     */
    private DesensitizationTypeEnum type;

    /**
     * 脱敏开始位置
     */
    private Integer startInclude;

    /**
     * 脱敏结束位置
     */
    private Integer endExclude;

    /**
     * 脱敏处理方法
     *
     * @param str                脱敏源
     * @param jsonGenerator      json自动生成
     * @param serializerProvider 序列化提供器
     */
    @Override
    public void serialize(String str, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {

        switch (type) {
            // 自定义类型脱敏
            case MY_RULE:
                jsonGenerator.writeString(CharSequenceUtil.hide(str, startInclude, endExclude));
                break;

            // userId 脱敏
            case USER_ID:
                jsonGenerator.writeString(String.valueOf(DesensitizedUtil.userId()));
                break;

            // 中文姓名脱敏
            case CHINESE_NAME:
                jsonGenerator.writeString(DesensitizedUtil.chineseName(str));
                break;

            // 身份证脱敏
            case ID_CARD:
                jsonGenerator.writeString(DesensitizedUtil.idCardNum(str, 1, 2));
                break;

            // 规定电话脱敏
            case FIXED_PHONE:
                jsonGenerator.writeString(DesensitizedUtil.fixedPhone(str));
                break;

            // 手机号脱敏
            case MOBILE_PHONE:
                jsonGenerator.writeString(DesensitizedUtil.mobilePhone(str));
                break;

            // 手机号脱敏
            case ADDRESS:
                jsonGenerator.writeString(DesensitizedUtil.address(str, 8));
                break;

            // 邮箱脱敏
            case EMAIL:
                jsonGenerator.writeString(DesensitizedUtil.email(str));
                break;

            // 原码脱敏
            case PASSWORD:
                jsonGenerator.writeString(DesensitizedUtil.password(str));
                break;

            // 中国车牌脱敏
            case CAR_LICENSE:
                jsonGenerator.writeString(DesensitizedUtil.carLicense(str));
                break;

            // 银行卡脱敏
            case BANK_CARD:
                jsonGenerator.writeString(DesensitizedUtil.bankCard(str));
                break;
            default:
        }

    }

    /**
     * createContextual
     *
     * @param serializerProvider 序列化提供者
     * @param beanProperty       bean属性
     * @return JsonSerializer
     */
    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {

        if (beanProperty != null) {
            // 判断数据类型是否为 String类型
            if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
                // 获取定义的注解
                Desensitization desensitization = beanProperty.getAnnotation(Desensitization.class);
                if (desensitization == null) {
                    desensitization = beanProperty.getContextAnnotation(Desensitization.class);
                }
                if (desensitization != null) {
                    // 创建自定义的序列化类的实例并且返回, 入参为注解定义的 type, 开始位置, 结束位置
                    return new DesensitizationSerialize(desensitization.type(), desensitization.startInclude(), desensitization.endExclude());
                }
            }
            return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
        }
        return serializerProvider.findNullValueSerializer(null);
    }
}
